package main

import (
	"fmt"
	"testing"
)

type ImageFlyweightFactory struct {
	maps map[string]*ImageFlyweight
}

var imageFactory *ImageFlyweightFactory

func GetImageFlyweightFactory() *ImageFlyweightFactory { // 创建一个存储对象的map
	if imageFactory == nil {
		imageFactory = &ImageFlyweightFactory{
			maps: make(map[string]*ImageFlyweight),
		}
	}
	return imageFactory
}

func (f *ImageFlyweightFactory) Get(filename string) *ImageFlyweight { // 创建一个ImageFlyweight对象并返回这个对象
	image := f.maps[filename]
	if image == nil {
		image = NewImageFlyweight(filename)
		f.maps[filename] = image
	}

	return image
}

type ImageFlyweight struct {
	data string
}

func NewImageFlyweight(filename string) *ImageFlyweight { // 创建ImageFlyweight对象
	// Load image file
	data := fmt.Sprintf("image data %s", filename)
	return &ImageFlyweight{
		data: data,
	}
}

func (i *ImageFlyweight) Data() string {
	return i.data
}

type ImageViewer struct {
	*ImageFlyweight
}

func NewImageViewer(filename string) *ImageViewer { // 创建一个ImageViewer对象
	image := GetImageFlyweightFactory().Get(filename)
	return &ImageViewer{
		ImageFlyweight: image,
	}
}

func (i *ImageViewer) Display() { // 显示这个对象
	fmt.Printf("Display: %s\n", i.Data())
}

func main() {
	viewer := NewImageViewer("image1.png")
	viewer.Display()
	// Output:
	// Display: image data image1.png

	TestFlyweightTest(&testing.T{})
}

func TestFlyweightTest(t *testing.T) {
	viewer1 := NewImageViewer("image1.png") // 创建对象
	viewer2 := NewImageViewer("image1.png") // 创建对象

	if viewer1.ImageFlyweight != viewer2.ImageFlyweight { // 获取两个对象比较结果
		fmt.Println("不同的对象：", viewer1.data, viewer2.data)
	} else {
		fmt.Println("地址相同：", viewer1.ImageFlyweight)
	}
}

/*
享元模式


这些对象有很多相似的地方，如果能把它们相同的部分提取出来共享，则能节省大量的系统资源，这就是享元模式的产生背景。
享元（Flyweight）模式的定义：
	运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销，从而提高系统资源的利用率。


享元模式的主要优点是：
	相同对象只要保存一份，这降低了系统中对象的数量，从而降低了系统中细粒度对象给内存带来的压力。


其主要缺点是：
	为了使对象可以共享，需要将一些不能共享的状态外部化，这将增加程序的复杂性。
	读取享元模式的外部状态会使得运行时间稍微变长。


# 享元模式
	享元模式从对象中剥离出不发生改变且多个实例需要的重复数据，独立出一个享元，使多个对象共享，从而节省内存以及减少对象数量。




*/
